﻿using System;

namespace TY.UC.Common
{
    /// <summary>
    /// 经纬度距离计算
    /// </summary>
    public class DistanceHelper
    {
        static double DEF_PI = 3.14159265359; // PI
        static double DEF_2PI = 6.28318530712; // 2*PI
        static double DEF_PI180 = 0.01745329252; // PI/180.0
        static double DEF_R = 6370693.5; // radius of earth
        static double EARTH_RADIUS = 6371.0;//km 地球半径 平均值，千米
        /// <summary>
        /// 计算两个经纬度之间直线距离
        /// </summary>
        /// <param name="lon1"></param>
        /// <param name="lat1"></param>
        /// <param name="lon2"></param>
        /// <param name="lat2"></param>
        /// <returns></returns>
        public static double GetShortDistance(double lon1, double lat1, double lon2, double lat2)
        {
            // 角度转换为弧度
            var ew1 = lon1 * DEF_PI180;
            var ns1 = lat1 * DEF_PI180;
            var ew2 = lon2 * DEF_PI180;
            var ns2 = lat2 * DEF_PI180;
            // 经度差
            var dew = ew1 - ew2;
            // 若跨东经和西经180 度，进行调整
            if (dew > DEF_PI)
                dew = DEF_2PI - dew;
            else if (dew < -DEF_PI)
                dew = DEF_2PI + dew;
            var dx = DEF_R * Math.Cos(ns1) * dew;
            var dy = DEF_R * (ns1 - ns2);
            // 勾股定理求斜边长
            var distance = Math.Sqrt(dx * dx + dy * dy);
            return distance;
        }

        /// <summary>
        /// 计算两个经纬度之间的球面距离
        /// </summary>
        /// <param name="lat1"></param>
        /// <param name="lon1"></param>
        /// <param name="lat2"></param>
        /// <param name="lon2"></param>
        /// <returns></returns>
        public static double Distance(double lat1, double lon1, double lat2, double lon2)
        {
            //用haversine公式计算球面两点间的距离。
            //经纬度转换成弧度
            lat1 = ConvertDegreesToRadians(lat1);
            lon1 = ConvertDegreesToRadians(lon1);
            lat2 = ConvertDegreesToRadians(lat2);
            lon2 = ConvertDegreesToRadians(lon2);

            //差值
            var vLon = Math.Abs(lon1 - lon2);
            var vLat = Math.Abs(lat1 - lat2);

            //h is the great circle distance in radians, great circle就是一个球体上的切面，它的圆心即是球心的一个周长最大的圆。
            var h = HaverSin(vLat) + Math.Cos(lat1) * Math.Cos(lat2) * HaverSin(vLon);

            var distance = 2 * EARTH_RADIUS * Math.Asin(Math.Sqrt(h));

            return distance;
        }
        /// <summary>
        /// 将角度换算为弧度。
        /// </summary>
        /// <param name="degrees">角度</param>
        /// <returns>弧度</returns>
        private static double ConvertDegreesToRadians(double degrees)
        {
            return degrees * Math.PI / 180;
        }

        public static double ConvertRadiansToDegrees(double radian)
        {
            return radian * 180.0 / Math.PI;
        }

        private static double HaverSin(double theta)
        {
            var v = Math.Sin(theta / 2);
            return v * v;
        }

        private static double rad(double d)
        {
            return d * Math.PI / 180.0;
        }
       
    }
}

